package org.mte.sakn.util;


import java.io.Serializable;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/**
 * ListSet
 *
 * @author Marco Traversari
 * @version $Revision: 1.1 $ $Date: 2012-08-24 13:14:28 $ $Author: marco $
 */
public class ListSet<E> implements Serializable {
	
	/**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = 692478946464656407L;
	
	/**
	 * entities
	 */
	protected List<E> entities = null;

	/**
	 * getEntities
	 * @return entities
	 */
	public List<E> getEntities() {
		return entities;
	}

	/**
	 * setEntities
	 * @param entities
	 */
	public void setEntities(List<E> entities) {
		this.entities = entities;
	}

	/**
	 * add
	 * @param entity
	 */
	public void add(E entity) {
		if (entities == null) {
			entities = new ArrayList<E>();
		}
		entities.add(entity);
	}

	/**
	 * getEntity
	 * @param index
	 * @return entity
	 */
	public E get(int index) {
		E entity = null;
		if (entities != null) {
			entity = entities.get(index);
		}
		return entity;
	}

	/**
	 * get
	 * @param name
	 * @return entity
	 */
	public E get(Object cValue, String className, String getter) {
		E entity = null;
		if (entities != null) {
			Iterator<E> iterator = entities.iterator();
			while (iterator.hasNext() && entity == null) {
				E entt =  iterator.next();
				E ivalue = invokeGetter(entt, className, getter);				 
				entity = (compare(ivalue, cValue)) ? (E) entt : null;
			}
		}
		return entity;
	}
	
	private boolean compare(Object ivalue, Object cvalue) {
		boolean isEqual = false;
		if (ivalue != null && cvalue != null) {
			if (cvalue instanceof Integer) {
				Integer i = (Integer) ivalue;
				Integer c = (Integer) cvalue;
				isEqual = i.intValue() == c.intValue();
			} else if (cvalue instanceof Long) {
				Long i = (Long) ivalue;
				Long c = (Long) cvalue;
				isEqual = i.intValue() == c.intValue();
			} else if (cvalue instanceof Float) {
				Float i = (Float) ivalue;
				Float c = (Float) cvalue;
				isEqual = i.floatValue() == c.floatValue();
			} else if (cvalue instanceof Double) {
				Double i = (Double) ivalue;
				Double c = (Double) cvalue;
				isEqual = i.doubleValue() == c.doubleValue();		
			} else if (cvalue instanceof BigDecimal) {
				BigDecimal i = (BigDecimal) ivalue;
				BigDecimal c = (BigDecimal) cvalue;
				isEqual = i.doubleValue() == c.doubleValue();				
			} else {
				String i = (String) ivalue;
				String c = (String) cvalue;
				isEqual = i.equals(c);
			}
		}
		return isEqual;
	}
	

	
	/**
	 * isEmpty
	 * @return isEmpty
	 */
	public boolean isEmpty() {
		return entities == null || entities.size() == 0;
	}
	
	/**
	 * isNotEmpty
	 * @return isNotEmpty
	 */
	public boolean isNotEmpty() {
		return !isEmpty();
	}
	
	@SuppressWarnings("unchecked")
	private <T> T invokeGetter(Object object, String className, String methodName) {
		T value = null;
		try {
			Class<T> clazz = (Class<T>) object.getClass();
			Method method = clazz.getMethod(methodName);
			Object[] args = null;
			Object objectValue =  (Object) method.invoke(object, args);
			Class<T> objectToCastClass = (Class<T>) Class.forName(className);
			value = objectToCastClass.cast(objectValue);			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return value;
	}
}
